package com.srwl.mytx.im.conversation;

import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.srwl.mytx.Constant;
import com.srwl.mytx.Helper;
import com.srwl.mytx.MyApplication;
import com.srwl.mytx.RetrofitManager;
import com.srwl.mytx.activity.ChatActivity;
import com.srwl.mytx.dao.DBManager;
import com.srwl.mytx.domain.CommonResult;
import com.srwl.mytx.domain.ConversationData;
import com.srwl.mytx.domain.Message;
import com.srwl.mytx.domain.User;
import com.srwl.mytx.greendao.ConversationDataDao;
import com.srwl.mytx.im.ConversationListener;
import com.srwl.mytx.im.MessageHandler;
import com.srwl.mytx.service.UserService;
import com.srwl.mytx.utils.ChatMessageUtil;
import com.srwl.mytx.utils.IDUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;


public class Conversation {

    protected String cId;
    protected int unReadCount;
    protected int type;

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    protected ConversationDataDao conversationDataDao;
    //消息监听
    protected MessageListener messageListener;
    protected MessageHandler messageHandler;
    protected MessageUnReadCountListener unReadCountListener;
    protected Message lastMessage;
    protected ConversationListener conversationListener;
    private int downPullPage;//下拉加载的页数
    private int pullUpPage;//上拉加载的页数
    private int size;
    private boolean hasMoreDownPullMessage = true;//标记下拉是否还能加载更多的消息
    private boolean hasMorePullUpMessage = true;//标记上拉 是否  还能加载更多的消息

    //从第一次加载本地消息开始（打开聊天页面），收到的或者发出的消息数量，
    private int newMessageSize;
    //从第一次加载本地消息开始，删除的信息数量
    private int deleteMessageSize;

    //消息接收者id
    private String toUserId;

    private User toUser;

    List<Message> messageList;
    private int startIndex;//第一次加载消息记录  开始索引
    private int endIndex; // 第一次加载消息记录 结束索引

    private static final String TAG = "Conversation";

    protected ConversationData data;
    //会话页面是否在后台
    protected boolean isActivityInBackstage;

    //临时会话标记
    protected boolean isTempConversation = true;

    public Conversation() {
    }

    public Conversation(String toUserId, int type) {
        data = new ConversationData(toUserId, 0, type);
        this.cId = toUserId;
        this.toUserId = toUserId;
        this.type = type;
        conversationDataDao = DBManager.getInstance().getDaoSession().getConversationDataDao();
        queryUserInfo();
    }

    public Conversation(String toUserId, int type, MessageHandler messageHandler, MessageUnReadCountListener unReadCountListener) {
        data = new ConversationData(toUserId, 0, type);
        this.messageHandler = messageHandler;
        this.unReadCountListener = unReadCountListener;
        this.cId = toUserId;
        this.toUserId = toUserId;
        this.type = type;
        conversationDataDao = DBManager.getInstance().getDaoSession().getConversationDataDao();
        loadLastMessage();
        queryUserInfo();
    }

    public Conversation(ConversationData data, MessageHandler messageHandler, MessageUnReadCountListener unReadCountListener) {
        this.data = data;
        this.messageHandler = messageHandler;
        this.unReadCountListener = unReadCountListener;
        cId = data.getCId();
        toUserId = cId;
        this.type = data.getType();
        unReadCount = data.getUnReadCount();
        //根据会话数据中保存的消息未读数，回调出去
        if (unReadCount != 0 && unReadCountListener != null) {
            unReadCountListener.onReadCountAdd(unReadCount);
        }
        conversationDataDao = DBManager.getInstance().getDaoSession().getConversationDataDao();
        loadLastMessage();
        queryUserInfo();
    }

    public void loadLastMessage() {

        lastMessage = messageHandler.loadLastMessage(data.getCId());
    }

    public void receivedMessage(Message message) {
        //收到已读消息回执 当成消息状态更新处理
        if (message.getSubType() == Constant.IM_TYPE_MESSAGE_READ_ACK) {
            if (messageListener != null) {
                messageListener.onMessageReadStateChange(message);
            }
            messageHandler.setLocalMessageRead(message.getContent());
            return;
        }
        //对收到的消息，清理下载状态，避免发送的时候，没清理，而影响文件类型消息的下载
        message.setDownloadState(null);
        newMessageSize++;
        lastMessage = message;
        if (messageListener != null) {
            messageListener.onReceiveMessage(message);
            //判断会话页面是否是在后台，应该响铃
            if (isActivityInBackstage) {
                messageHandler.vibrateAndPlayTone();
            }
        } else {
            //当messageListener为空，即用户不在对应的聊天页面的时候，消息未读数才需要添加
            unReadCount++;
            messageHandler.vibrateAndPlayTone();
            if (unReadCountListener != null) {
                unReadCountListener.onReadCountAdd(1);
            }
        }
        //收到对方发给我的消息，需要设置cid 为当前会话的id ,再保存
        message.setcId(cId);
        message.setReadState(Constant.MESSAGE_READ_STATE_UNREAD);
        messageHandler.saveMessage(message);
        Log.d(TAG, "receivedMessage:当前未读数 unReadCount: " + unReadCount);
        data.setUnReadCount(unReadCount);
        data.setUpdated(new Date());//设置更新时间，用于从数据库加载会话列表的时候，按更新时间排序
        conversationDataDao.insertOrReplace(data);
    }

    public void updateMessageSendState(Message message) {
        //比对当前更新的消息是否是会话中持有的最后一条消息，并更新状态
        if (lastMessage != null && TextUtils.equals(lastMessage.getId(), message.getId())) {
            lastMessage.setSendState(message.getSendState());
        }
        if (messageListener != null) {
            messageListener.onMessageSendStateChange(message);
        }
    }

    public int getUnReadCount() {
        return unReadCount;
    }


    /**
     * 删除所有消息
     */
    public void deleteAllMessage() {
        if (messageHandler == null) {
            return;
        }
        messageHandler.deleteAllMessage(cId);

        if (messageListener != null) {
            messageListener.onDeleteAllMessage();
        }
        //上报未读数变动
        if (unReadCountListener != null && unReadCount != 0) {
            unReadCountListener.onReadCountReduce(unReadCount);
        }
        unReadCount = 0;
        data.setUnReadCount(0);
        conversationDataDao.insertOrReplace(data);
        hasMoreDownPullMessage = false;

    }

    /**
     * 一次删除一条消息
     *
     * @param deleteMessage
     */
    public void deleteMessage(Message deleteMessage) {
        if (messageHandler == null) {
            return;
        }
        messageHandler.deleteMessage(deleteMessage);
        deleteMessageSize++;
        if (messageListener != null) {
            messageListener.onMessageDelete(deleteMessage);
        }
        int allMessageCount = messageHandler.queryMessageSizeByConversationId(cId);
        if (allMessageCount == 0) {
            conversationListener.onConversationRemove(this);
        }


    }


    /**
     * 设置消息已读状态，保存消息状态到本地，并发送一条已读回执给消息的发送者
     */
    public void setMessageRead(Message message) {
        //unReadCount--;
        message.setReadState(Constant.MESSAGE_READ_STATE_READ);
        //messageHandler.updateMessage(message);
        messageHandler.setLocalMessageRead(message.getId());
//        if (unReadCountListener != null) {
//            conversationDao.insertOrReplace(this);
//            unReadCountListener.onReadCountReduce(1);
//        }

        String toId = message.getToId();
        String fromId = message.getFromId();
        //必须重新生成一个ackMessage，而不能在 传入的message上修改
        //调换收发消息的双方
        //不用携带 已读状态，对方收到 READ_ACK 消息，只管设置状态为已读即可，因为没有更多状态了，
        //也可以利用类似的机制做消息拆回功能，如果拆回功能有必须要的话，
        Message ackMessage = new Message();
        ackMessage.setId(IDUtils.genOrderItemId());
        ackMessage.setToId(fromId);
        ackMessage.setFromId(toId);
        ackMessage.setContent(message.getId());//收到已读回执的一方，从content中取出 目标消息id
        ackMessage.setType(Constant.C2C_MESSAGE);
        ackMessage.setSubType(Constant.IM_TYPE_MESSAGE_READ_ACK);
        //设置该消息为不可见，不增加未读消息数量，但是需要 更新对应消息的读取状态
        ackMessage.setVisible(Constant.MESSAGE_INVISIBLE);

        try {
            messageHandler.sendMessage(ackMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void setMessageListener(MessageListener messageListener) {
        this.messageListener = messageListener;
    }


    public String getCId() {
        return this.cId;
    }

    public void setCId(String cId) {
        this.cId = cId;
    }

    public void setMessageHandler(MessageHandler messageHandler) {
        this.messageHandler = messageHandler;
    }

    public void setUnReadCountListener(MessageUnReadCountListener unReadCountListener) {
        this.unReadCountListener = unReadCountListener;
    }

    public Message getLastMessage() {
        return lastMessage;
    }


    public void sendMessage(Message message) {
        message.setId(IDUtils.genOrderItemId());
        //设置消息发送状态
        message.setSendState(Constant.IM_SEND_STATE_SENDING);
        //设置消息为可见类型消息，收到消息需要增加 未读消息数量
        message.setVisible(Constant.MESSAGE_VISIBLE);
        //设置消息的发送者
        message.setToId(toUserId);
        //设置消息所属的会话id
        message.setcId(cId);
        //设置消息读取状态为未读
        message.setReadState(Constant.MESSAGE_READ_STATE_UNREAD);
        //不能直接new Date ，因为客户端时间可能是手动修改过的，加上时间偏移量，以此来还原 系统时间
        long serviceTime = System.currentTimeMillis() + MyApplication.timeOffset;
        Date created = new Date(serviceTime);
        message.setCreated(created);
        try {
            messageHandler.sendMessage(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
        lastMessage = message;
        newMessageSize++;
        if (messageListener != null) {
            messageListener.onReceiveMessage(message);
        }
    }

    public void reSendMessage(Message message) {
        try {
            messageHandler.sendMessage(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setToUserId(String toUserId) {
        this.toUserId = toUserId;
    }

    public String getToUserId() {
        return toUserId;
    }

    public void queryUserInfo() {
        User contactUserInfo = Helper.getInstance().getContactUserInfo(toUserId);
        if (contactUserInfo != null) {
            toUser = contactUserInfo;
        } else {
            getUserInfo(toUserId);
        }

    }

    public User getToUser() {
        return toUser;
    }

    public void setToUser(User toUser) {
        this.toUser = toUser;
    }

    /**
     * 第一次加载本地消息
     * 从最新的消息开始加重
     *
     * @param size
     */
    public List<Message> firstLoadMessage(int size) {
        if (cId == null) {
            Log.e(TAG, "firstLoadMessage: cId 为空");
            return Collections.emptyList();
        }

        if (messageHandler == null) {
            Log.e(TAG, "firstLoadMessage: messageHandler 为空");
            return Collections.emptyList();
        }
        this.size = size;
        newMessageSize = 0;
        pullUpPage = 0;
        downPullPage = 0;
        hasMorePullUpMessage = true;
        hasMoreDownPullMessage = true;
        List<Message> messages = messageHandler.loadMoreMessage(startIndex, size, cId);
        //第一次加载后,下拉加载的页数 增加1；
        pullUpPage++;
        //第一次加载本地消息，是以起始索引，向下（以数据库表中按创建时间降序排列来说）加载，所以加载之后，downPullPage 加1
        if (messages != null && messages.size() == size) {
            hasMoreDownPullMessage = true;
            downPullPage++;
        } else {
            hasMoreDownPullMessage = false;
            if (messageListener != null) {
                messageListener.onNoMorePullDownMessage();
            }

        }
        if (messages != null) {
            endIndex = startIndex - messages.size();
            //Collections.reverse(messages);
        }
//        if (messageListener != null && messages != null) {
//            endIndex = startIndex - messages.size();
//            //对消息列表进行反转，因为从数据库读取是按创建时间降序排列的，
//            Collections.reverse(messages);
//            messageListener.onPullDownLoadMoreLocalMessage(messages);
//        }
        return messages;
    }

    /**
     * 给定加载消息记录的起始点
     *
     * @param size
     * @return
     */
    public List<Message> firstLoadMessage(int size, int startIndex) {
        this.startIndex = startIndex;
        return firstLoadMessage(size);
    }

    /**
     * 下拉加载更多本地消息
     * 加载的是比第一次加载的时间上更旧一些的消息，
     */
    public void pullDownLoadMoreMessage() {
        if (cId == null || messageHandler == null || !hasMoreDownPullMessage) {
            if (messageListener != null) {
                messageListener.onPullDownLoadMoreLocalMessage(Collections.EMPTY_LIST);
            }
            return;
        }
        //加载更多的时候，不能直接以 downPullPage 和size 去获取分页消息，因为在这期间，可能在不断收发消息和删除消息，
        //应该以 结束索引 当前页数和每页的数之积 + 收发的新消息数量 - 删除的消息数量
        int offset = startIndex + downPullPage * size + newMessageSize - deleteMessageSize;
        Log.d(TAG, "pullDownLoadMoreMessage: offset:" + offset);
        List<Message> messages = messageHandler.loadMoreMessage(offset, size, cId);
        if (messages != null && messages.size() == size) {
            hasMoreDownPullMessage = true;
            downPullPage++;
        } else {
            hasMoreDownPullMessage = false;
        }
        if (messageListener != null) {
            if (messages != null) {

                messageListener.onPullDownLoadMoreLocalMessage(messages);
            } else {
                messageListener.onPullDownLoadMoreLocalMessage(Collections.EMPTY_LIST);
            }
        }
    }

    /**
     * 上拉加载更多本地消息
     * 加载的是比第一次加载的时间上更新一些的消息，
     */
    public void pullUpLoadMoreMessage() {
        if (cId == null || messageHandler == null || !hasMorePullUpMessage) {
            if (messageListener != null) {
                messageListener.onPullUpLoadMoreLocalMessage(Collections.EMPTY_LIST);
            }
            return;
        }
        //加载更多的时候，不能直接以 downPullPage 和size 去获取分页消息，因为在这期间，可能在不断收发消息和删除消息，
        //应该以  开始索引 - 当前页数和每页的数之积 +收发的新消息数量 ，
        // 不受删除的消息数量的影响
        int offset = startIndex - pullUpPage * size + newMessageSize;
        if (offset < 0) {
            if (messageListener != null) {
                messageListener.onPullUpLoadMoreLocalMessage(Collections.EMPTY_LIST);
            }
            return;
        }
        int loadSize = size;
        if (startIndex - pullUpPage * size < size) {
            loadSize = startIndex - pullUpPage * size; //不满页的情况
            offset = newMessageSize;
        }
        List<Message> messages = messageHandler.loadMoreMessage(offset, loadSize, cId);
        if (messages != null && messages.size() == size) {
            hasMorePullUpMessage = true;
            pullUpPage++;
        } else {
            hasMorePullUpMessage = false;
        }
        if (messageListener != null) {
            if (messages != null) {

                messageListener.onPullUpLoadMoreLocalMessage(messages);
            } else {
                messageListener.onPullUpLoadMoreLocalMessage(Collections.EMPTY_LIST);
            }
        }
    }


    public void setUnReadCount(int unReadCount) {
        this.unReadCount = unReadCount;
        data.setUnReadCount(unReadCount);
        conversationDataDao.insertOrReplace(data);
    }


    public void addMessage(Message message) {

        if (messageList == null) {
            messageList = new ArrayList<>();
        }
        messageList.add(message);
    }

    public int getNewMessageSize() {
        return newMessageSize;
    }

    public List<Message> getMessageList() {
        if (messageList == null) {
            messageList = new ArrayList<>();
        }
        return messageList;
    }

    /**
     * 保存会话数据进数据库，当app 启动的时候，才能从数据库中读取出会话
     */
    public void saveData() {
        try {
            conversationDataDao.insertOrReplace(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void deleteData() {
        conversationDataDao.delete(data);
    }


    public String getTitle() {
        if (toUser == null) {
            return null;
        }
        String username = toUser.getUsername();
        return username != null ? username : toUser.getNick();
    }

    public String getIcon() {
        if (toUser == null) {
            return null;
        }
        return toUser.getAvatar();
    }

    public int getIconResourceId() {
        return 0;
    }

    public String getContent() {
        return ChatMessageUtil.getMessageDigest(lastMessage);
    }


    /**
     * 打开会话
     * 就是进入聊天页面
     *
     * @param context
     */
    public void openConversation(Context context) {


        Intent intent = new Intent(context, ChatActivity.class);
        if (toUser == null) {//如果目标对象为空（这个情况属于本地没有这个用户信息，需要去服务端加载），就new 一个，先进入聊天页面，等用户信息 从服务端好了，再通知聊天页面刷新
            toUser = new User(toUserId);
        }
        intent.putExtra(Constant.EXTRA_TARGET_USER_INFO, toUser);
        context.startActivity(intent);
        resetUnReadCount();
    }

    /**
     * 当打开会话进入聊天页面，清空未读数 ,保存进数据库 并通知出去，
     */
    public void resetUnReadCount() {
        if (unReadCount > 0) {
            if (unReadCountListener != null) {
                unReadCountListener.onReadCountReduce(unReadCount);
            }
            unReadCount = 0;
            data.setUnReadCount(0);
            conversationDataDao.update(data);
        }
    }

    /**
     * 关闭会话
     * 清理消息监听，否则会内存泄漏
     * 读取当前会话的所有消息数量，如果等于0，需要删除当前会话
     */
    public void clear() {
        messageListener = null;
    }


    public void setConversationListener(ConversationListener conversationListener) {
        this.conversationListener = conversationListener;
    }

    public void removeConversationListener() {
        conversationListener = null;
    }

    /**
     * 设置 会话页面是在前台还是在后台
     *
     * @param activityInBackstage
     */
    public void setActivityInBackstage(boolean activityInBackstage) {
        isActivityInBackstage = activityInBackstage;
    }

    /**
     * 远程查询用户信息
     *
     * @param userId
     */
    private void getUserInfo(String userId) {
        RetrofitManager.getInstance().createRequest(UserService.class)
                .getUserInfo(userId)
                .enqueue(new Callback<CommonResult>() {
                    @Override
                    public void onResponse(Call<CommonResult> call, Response<CommonResult> response) {
                        CommonResult result = response.body();
                        if (!response.isSuccessful() || result == null) {
                            Log.e(TAG, "onResponse:从服务端获取联系人信息出错 " + response.message());
                            return;
                        }

                        if (result.isError()) {
                            Log.e(TAG, "onResponse:从服务端获取联系人信息出错 " + result.getMsg());
                            return;
                        }

                        JSONObject object = (JSONObject) result.getData();

                        User user = object.toJavaObject(User.class);
                        user.setUId(userId);
                        user.setType(Constant.USER_TYPE_TEMP);
                        DBManager.getInstance().getDaoSession().getUserDao().insertOrReplace(user);//作为临时联系人，保存在用户表中
                        toUser = user;
                        if (conversationListener != null) {
                            conversationListener.onUserInfoChange(Conversation.this);
                        }

                        if (messageListener != null) {
                            messageListener.onTargetUserInfoRefresh(toUser);
                        }
                    }

                    @Override
                    public void onFailure(Call<CommonResult> call, Throwable t) {

                        Log.e(TAG, "onFailure: " + t.getMessage());
                    }
                });
    }

    /**
     * 当聊天对象用户信息改变,
     * 需要通过会话列表和聊天界面做刷新
     */
    public void onTargetUserInfoChange(User newUserInfo) {
        toUser = newUserInfo;
        //当不是零时会话的时候，才更新到会话列表，（临时会话：还没有显示到会话列表的会话）
        if (!isTempConversation && conversationListener != null) {
            conversationListener.onUserInfoChange(Conversation.this);
        }
        if (messageListener != null) {
            messageListener.onTargetUserInfoRefresh(toUser);
        }
    }

    public void setTempConversation(boolean tempConversation) {
        isTempConversation = tempConversation;
    }

    public void updatePosition(Integer currentPosition) {
        data.setPosition(currentPosition);
        conversationDataDao.update(data);
    }

    /**
     * 判断是否置顶
     *
     * @return
     */
    public boolean isTop() {
        return data.getPosition() != ConversationData.DEFAULT_POSITION;
    }

    public interface MessageListener {
        /**
         * 加载更多本地消息之后的回调
         * 本地消息插入到消息列表的前面，而不是追求到后面
         *
         * @param messageList
         */
        void onPullDownLoadMoreLocalMessage(List<Message> messageList);

        /**
         * 上拉加载更多消息
         *
         * @param messages
         */
        void onPullUpLoadMoreLocalMessage(List<Message> messages);

        void onNoMorePullDownMessage();

        void onReceiveMessage(Message message);

        /**
         * 当消息删除
         *
         * @param
         */
        void onMessageDelete(Message deleteMessage);

        void onDeleteAllMessage();

        void onMessageSendStateChange(Message message);

        void onMessageReadStateChange(Message message);

        void onTargetUserInfoRefresh(User targetUser);
    }

    public interface MessageUnReadCountListener {
        void onReadCountReduce(int count);

        void onReadCountAdd(int count);
    }

}
